package com.ssb.admin.common.aspect;

import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ssb.admin.common.annotation.OptLog;
import com.ssb.admin.common.utils.ShiroUtils;
import com.ssb.admin.constant.OptLogConstant;
import com.ssb.admin.modules.sys.log.entity.SysLog;
import com.ssb.admin.modules.sys.log.service.ISysLogService;
import com.ssb.admin.modules.sys.user.entity.SysUser;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Aspect
@Component
public class OptLogAspect {

    private final ISysLogService sysLogService;

    @Autowired
    public OptLogAspect(ISysLogService sysLogService) {
        this.sysLogService = sysLogService;
    }

    @Pointcut("@annotation(com.ssb.admin.common.annotation.OptLog)")
    public void logPointCut() {

    }

    @Around("logPointCut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        long beginTime = System.currentTimeMillis();
        MethodSignature signature = (MethodSignature) point.getSignature();
        Method method = signature.getMethod();
        OptLog syslog = method.getAnnotation(OptLog.class);

        //保存日志
        if (syslog.isBefore()) {
            saveSysLog(point, signature, syslog, 0);
        }
        //执行方法
        Object result = point.proceed();
        //执行时长(毫秒)
        long time = System.currentTimeMillis() - beginTime;

        //保存日志
        if (syslog.isAfter()) {
            saveSysLog(point, signature, syslog, time);
        }

        return result;
    }

    private void saveSysLog(ProceedingJoinPoint joinPoint, MethodSignature signature, OptLog optLog, long time) {

        SysLog sysLog = new SysLog();

        OptLogConstant type = optLog.value();
        sysLog.setOptType(type.code);

        //请求的方法名
        String className = joinPoint.getTarget().getClass().getName();
        String methodName = signature.getName();
        //方法名
        sysLog.setOptMethod(className + "." + methodName + "()");


        //请求的参数
        Object[] args = joinPoint.getArgs();
        ObjectMapper mapper = new ObjectMapper();
        try {
            Map<String, Object> argMap = new HashMap<>(16);
            for (int index = 0; index < args.length; index++) {
                Object arg = args[index];
                if (arg instanceof HttpServletRequest) {
                    continue;
                }
                if (arg instanceof ServiceImpl) {
                    continue;
                }
                if (arg instanceof HttpServletResponse) {
                    continue;
                }
                argMap.put(index + "", mapper.writeValueAsString(arg));
            }
            String argsStr = mapper.writeValueAsString(argMap);
            sysLog.setOptParams(argsStr);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        //用户名
        SysUser sysUser= ShiroUtils.getUserInfo();
        if(sysUser!=null) {
            sysLog.setRoleName(sysUser.getRole().getRole());
            sysLog.setLoginName(sysUser.getLoginName());
            sysLog.setCreateTime(new Date());
            sysLog.setOptTime(time);
            //设置IP地址
            sysLog.setClientIp(sysUser.getIp());
            //保存系统日志
            sysLogService.asynInsert(sysLog);
        }
    }
}
